/* eslint-disable eslint-comments/disable-enable-pair */
/* eslint-disable no-param-reassign */
import React, { PureComponent } from 'react';
import {
  DatePicker,
  Select,
  Input,
  Button,
  Form,
  TreeSelect,
  ConfigProvider,
} from 'antd';
import { connect } from 'dva';
import zhCN from 'antd/lib/locale/zh_CN';
import moment from 'moment';
import { SearchOutlined } from '@ant-design/icons';
import styles from './index.less';

const { RangePicker } = DatePicker;

const dateFormat = 'YYYY-MM-DD';
const { Option } = Select;
export const firstToUpper = str => str.charAt(0).toUpperCase() + str.substr(1);

/**
 * 树形结构转换，用于匹配 TreeSelect 格式
 *
 * @param {array} treeData 转换数据列表
 * @param {string} label 对应 label 字段名
 * @param {string} value 对应 value 字段名
 * @returns
 */
export const treeDataTrans = (treeData, label, value) => {
  treeData.forEach(v => {
    v.title = v[label];
    v.value = v[value];
    v.key = v[value];
    // 异步数据存在 root 字段，该字段会影响 TreeSelect 渲染，移除字段
    delete v.root;
    if (v.children && v.children.length > 0) {
      treeDataTrans(v.children, label, value);
    }
  });
  return treeData;
};

/**
 * filters
 */
// @Form.create()
@connect(store => ({ $store: store }))
class FilterSearch extends PureComponent {
  static defaultProps = {
    filters: [],
    // 搜索
    onSearch: () => {},
    onRef: () => {},
  };
  state = {
    opts: {},
  };
  formRef = React.createRef();
  componentDidMount() {
    this.props.onRef(this);
    const { filters, dispatch } = this.props;
    const { opts } = this.state;
    let keys = [],
      pros = [];
    filters.forEach(({ options, key, asyncopt }) => {
      if (asyncopt && asyncopt.url) {
        keys.push(key);
        pros.push(
          dispatch({
            type: `$request/post`,
            payload: {
              url: asyncopt.url,
              data: { page: 0, size: 20, ...asyncopt.data },
            },
          }),
        );
      }
    });
    if (!pros.length) return;
    Promise.all(pros).then(res => {
      keys.forEach((key, index) => {
        let list = (res[index].dataList || res[index]).map(item => {
          return {
            label: item.name || item.display,
            value: item.uuid,
          };
        });
        opts[key] = list;
      });
      this.setState({ opts });
    });
  }

  /**
   * 设置一组输入控件的值
   *
   * @param {object} params {[fieldName]: value}
   */
  setValue = params => {
    this.formRef.current.setFieldsValue(params);
  };

  /**
   * 获取一组输入控件的值，如不传入参数，则获取全部组件的值
   *
   * @param {object} params [fieldNames: string[]]
   */
  getValue = params => {
    const values = this.formRef.current.getFieldsValue(params);
    const data = { ...values };
    return data;
  };

  /**
   * 重置一组输入控件的值
   *
   * @param {[string]} names [names: string[]]
   */
  onReset = () => {
    this.formRef.current.resetFields();
  };

  handleSubmit = values => {
    const data = { ...values };
    const keys = Object.keys(values);
    // 针对时间参数进行特殊转换，不然格式不对
    keys.forEach(key => {
      if (values[key] instanceof moment) {
        data[key] = new Date(data[key]).getTime();
      }
    });
    this.props.onSearch({ ...data });
  };

  render() {
    const { filters, children, style } = this.props;
    const { opts } = this.state;
    const getInputComp = filter => {
      let {
        key,
        type,
        label,
        mode, // 添加select多选模式，数据目前放在sumit回调给主页面去处理
        placeholder,
        options,
        config,
        compProps,
        render,
        format,
      } = filter;
      let result = null;

      options = options || opts[key];
      switch (type) {
        case 'input':
          result = (
            <Input
              allowClear
              placeholder={placeholder}
              style={{ width: 180 }}
            />
          );
          break;
        case 'date':
          result = (
            <DatePicker
              placeholder={placeholder}
              allowClear
              style={{ minWidth: 180 }}
            />
          );
          break;
        case 'rangepicker':
          result = (
            <RangePicker
              placeholder={placeholder}
              format={format || dateFormat}
              allowClear
              style={{ minWidth: 180 }}
            />
          );
          break;
        case 'select':
          result = (
            <Select
              showSearch
              optionFilterProp="children"
              placeholder={placeholder}
              allowClear
              mode={mode || ''}
              style={{ width: 180 }}
            >
              {options &&
                options.map((v, i) => (
                  <Option key={i} value={v.value}>
                    {v.label}
                  </Option>
                ))}
            </Select>
          );
          break;
        case 'treeSelect':
          result = (
            <TreeSelect
              treeData={options}
              showSearch
              treeNodeFilterProp="title"
              placeholder={placeholder}
              allowClear
              treeCheckable
              showCheckedStrategy={TreeSelect.SHOW_ALL}
              style={{ width: 180 }}
              dropdownStyle={{ maxHeight: 400 }}
            />
          );
          break;
        default:
          result = render || (
            <Input
              allowClear
              placeholder={placeholder}
              style={{ width: 180 }}
            />
          );
      }
      const props =
        typeof compProps === 'function'
          ? compProps(this.props.$store, this)
          : compProps;
      return (
        <Form.Item
          key={key}
          label={label}
          name={key}
          rules={config}
          style={{ marginBottom: 20 }}
        >
          {React.cloneElement(result, props)}
        </Form.Item>
      );
    };
    return (
      <ConfigProvider locale={zhCN}>
        <div className={styles.filter} style={style}>
          {filters.length > 0 && (
            <Form
              layout="inline"
              onFinish={this.handleSubmit}
              ref={this.formRef}
            >
              {filters.map(v => getInputComp(v))}
              <Form.Item>
                <Button
                  icon={<SearchOutlined />}
                  type="primary"
                  htmlType="submit"
                >
                  确定
                </Button>
                <Button onClick={this.onReset}>重置</Button>
              </Form.Item>
            </Form>
          )}
          {children && (
            <div className={filters.length > 0 ? styles.other : null}>
              {children}
            </div>
          )}
        </div>
      </ConfigProvider>
    );
  }
}
export default FilterSearch;
